﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FC.GEPluginCtrls;

namespace GE
{
    class CameraPipeline : UtilMPipeline
    {
        protected int nframes;
        protected bool device_lost;
        private FC.GEPluginCtrls.GEWebBrowser geWeb;
        private string m_gotoLoc;
        private ImageryBase m_ImageBase = ImageryBase.Earth;
        private MapType m_MapType = MapType.Earth;

        public delegate void CallWebInvoke();

        public void SetMapType(MapType m)
        {
            if(m != m_MapType)
            {
                try
                {
                    geWeb.Plugin.getOptions().setMapType(m);
                    m_MapType = m;
                }
                catch
                {
                }
            }

        }

        public void InvokeDoGeocode()
        {
            if (geWeb.InvokeRequired)
            {
                geWeb.Invoke(new CallWebInvoke(InvokeDoGeocode));
            }
            else
            {
                geWeb.InvokeDoGeocode(m_gotoLoc);
                m_gotoLoc = "";                
            }
        }

        public void InvokeNewBrowserInstance()
        {
            if(geWeb.InvokeRequired)
            {
                geWeb.Invoke(new CallWebInvoke(InvokeNewBrowserInstance));
            }
            else
            {
                geWeb.CreateInstance(m_ImageBase);
                m_gotoLoc = "";
            }
        }

        public bool IsDeviceLost()
        {
            return device_lost;
        }

        public CameraPipeline(FC.GEPluginCtrls.GEWebBrowser _geWeb): base()
        {
            EnableVoiceRecognition();
            nframes = 0;
            device_lost = false;
            geWeb = _geWeb;
        }

        public override bool OnDisconnect()
        {
            if (!device_lost) Console.WriteLine("Device disconnected");
            device_lost = true;
            return base.OnDisconnect();
        }

        public override void OnReconnect()
        {
            Console.WriteLine("Device reconnected");
            device_lost = false;
        }

        public override void OnRecognized(ref PXCMVoiceRecognition.Recognition data)
        {
            Console.WriteLine("\nRecognized<{0}>", data.dictation);
            string cmd = data.dictation.ToLower();
            if(cmd.StartsWith("go to "))
            {
                m_gotoLoc = cmd.Substring("go to ".Length);
                if (m_gotoLoc == "the moon" || m_gotoLoc == "mars" || m_gotoLoc == "the world")
                {
                    SetMapType(MapType.Earth);
                    ImageryBase imagebase;
                    switch (m_gotoLoc)
                    {
                        case "the moon":
                            imagebase = ImageryBase.Moon;
                            break;
                        case "mars":
                            imagebase = ImageryBase.Mars;
                            break;
                        default:
                            imagebase = ImageryBase.Earth;
                            break;
                    }
                    if (imagebase != m_ImageBase)
                    {
                        m_ImageBase = imagebase;
                        InvokeNewBrowserInstance();
                    }
                    m_gotoLoc = "";
                }
                else if (m_gotoLoc == "space")
                {
                    SetMapType(MapType.Sky);
                }
                else if(m_MapType == MapType.Earth && m_ImageBase == ImageryBase.Earth)
                {
                    if (m_gotoLoc == "haifa" || m_gotoLoc == "hi-fi")
                    {
                        m_gotoLoc = "matam haifa";
                    }

                    Console.WriteLine("Going to " + m_gotoLoc);
                    InvokeDoGeocode();
                }
            }
        }

        public override bool OnNewFrame()
        {
            return true;
        }
    };

    class Nori6UI
    {
        // public
        public Nori6UI(FC.GEPluginCtrls.GEWebBrowser geWeb)
        {
            camPipe = new CameraPipeline(geWeb);
            if (!camPipe.Init())
            {
                throw new Exception("Can't init camera");
            }
        }

        // This method will be called when the thread is started.
        public void DoWork()
        {
            try
            {
                while (!_shouldStop)
                {
                    if (!camPipe.IsDeviceLost() &&camPipe.AcquireFrame(false))
                    {
                        camPipe.ReleaseFrame();
                    }
                }
            }
            catch { }
        }

        public void RequestStop()
        {
            _shouldStop = true;
            camPipe.Close();
        }

        // Private
        private volatile bool _shouldStop;
        private CameraPipeline camPipe;
    }
}
